home *** CD-ROM | disk | FTP | other *** search
Wrap
/* ok, here's the news forger.. two caveats on this one: caveat #1: newer nntp servers insist on creating their own "NNTP-Posting-Host:" header and will balk the post if you try to forge it.. this header, while not usually displayed by most readers, is distributed in a post and usually contains the correct pseudo-authenticated machine that the socket connection was made from originally.. caveat #2: on one level, it seems that this is no better than sendmail or the forgepost no better than your run of the mill news poster - as it furthers people ability to ignore the mechanisms of things around them... further your mind and read the rfc's.. take care, loki (argh thru_ : contribute to the Process) -----news_forgery.h-------- */ /* written by Loki D. Quaeler (copyfree 1995) v1.0 */ /* #define DBUG */ #include <stdio.h> #include <strings.h> #include <errno.h> #include <signal.h> #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> #define NEWSPORT 119 #define MAXLEN 256 #define NNTP_INITIATE "POST" #define NNTP_CLOSE "QUIT" #define ORGANIZATION "Organization:" #define FROM "From:" #define SUBJECT "Subject:" #define NEWSGROUPS "Newsgroups:" #define DISTRIBUTION "Distribution:" #define MSGID "Message-ID:" #define NNTP_EODATA "." #define GOOD_CONNECT_STR "ready" #define GOOD_POST_ACK "240" #define BAD_NEWS "no posting" #define GOOD_DISCONNECT "205" #define QUIT_EXEC "quit" #define DIST_DEFAULT "world" #define MAX_HOSTLEN 64 #define null(type) (type) 0L #define NULL_STRING "" #ifndef YES #define YES 1 #define NO 0 #endif int s; /* socket number */ char buf[BUFSIZ+1]; /* global text data buffer */ char nntpHost[MAX_HOSTLEN]; char newsgroups[MAXLEN]; char pseudoSender[MAXLEN]; char organization[MAXLEN]; char subjectLine[MAXLEN]; char distribution[MAXLEN]; char messageID[MAXLEN]; char *body; /* by Loki D. Quaeler - copyfree 1995 */ #include "news_forgery.h" /*~~[ call_socket ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Connect to port MAILPORT on host 'hostname', returning the socket value. Return -1 on any errors. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ int call_socket(hostname) char *hostname; { struct sockaddr_in sa; struct hostent *hp; int a, sock; #ifdef DBUG printf("Entered call_socket, hostname = %s\n", hostname); #endif if ((hp=gethostbyname(hostname))==NULL) { errno=ECONNREFUSED; return(-1); } bzero(&sa, sizeof(sa)); bcopy(hp->h_addr, (char *)&sa.sin_addr, hp->h_length); sa.sin_family = hp->h_addrtype; sa.sin_port = htons((u_short)NEWSPORT); if((sock=socket(hp->h_addrtype, SOCK_STREAM, 0)) < 0) return(-1); if(connect(sock, &sa, sizeof(sa)) < 0) { close(sock); return(-1); } #ifdef DBUG printf("Exiting call_socket correctly, socket = %d\n", sock); #endif return(sock); } /*~~~[ readln ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Read all characters from socket s until a newline. Put resulting string in buf, ignoring all after the BUFSIZ'th character. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ int readln(buf) char *buf; { int to=0; char c; #ifdef DBUG printf("Entering readln\n"); #endif do { if(read(s, &c, 1)<1) return(0); if((c >= ' ') || (c <= 126)) if(to<BUFSIZ-1) buf[to++] = c; } while (c != '\n'); buf[to] = '\0'; #ifdef DBUG printf("buf = %s", buf); printf("Exiting readln correctly\n"); #endif return(1); } /*~~[ writeln ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Send contents of buf to socket s. Return 0 if the entire buf wasn't written. Return 1 on a successful write. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ int writeln(buf) char *buf; { int to=0; #ifdef DBUG printf("Entered writeln\n"); printf("buf = %s\n", buf); #endif /* buf[BUFSIZ] = '\0'; */ if( write(s, buf, strlen(buf)) < to ) return(0); #ifdef DBUG printf("Exited writeln correctly.\n"); #endif return(1); } /*~~[ main ]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Yes, main. amazing. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ main() { char inputString[BUFSIZ],outputString[BUFSIZ]; char *dataBody; int goodConnect = 0; printf("\n\nWelcome the news forgery Process...\n"); printf("\t- After all data is entered, a confirmation entry will be\n\t\tasked for before the actual connection is made.\n\n"); do { printf("~ Please enter NNTP server machine name\n\tor %s to exec program: ", QUIT_EXEC); gets(nntpHost); if (strcmp(nntpHost, QUIT_EXEC)) { goodConnect = contact_relay(); switch (goodConnect) { case 0: printf("** Could not reach host\n"); break; case 1: printf("** Host does not accept posting\n"); close(s); break; default: close(s); break; } } else exit(0); } while (goodConnect != 2); printf("~ Pseudonym (anything, any format): "); gets(pseudoSender); printf("~ Newsgroups to post to, multiple groups seperated\n\tby commas: "); gets(newsgroups); printf("~ Subject: "); gets(subjectLine); printf("~ Organization: "); gets(organization); printf("~ The distribution is defaulted to %s, enter a different one or\n\thit return: ", DIST_DEFAULT); gets(distribution); printf("~ Message-ID (ex: 23.23@ninth.circle.hell - *warning* some nntp\n\tservers do not like having this assigned for\n\tthem and will not correctly post because of\n\tit; hit return to skip this item) : "); gets(messageID); printf("~ Enter the body below, enter ctrl-d on a blank line to end text entry.\n---------\n"); body = (char *)malloc(2); sprintf(body,"\n"); while (gets(inputString) != NULL) { if (! strcmp(inputString, NNTP_EODATA)) sprintf(inputString,"%s.", NNTP_EODATA); body = (char *)realloc(body,((strlen(body) + strlen(inputString) + 2) * sizeof(char))); strcat(body,inputString); strcat(body,"\n"); } clearerr(stdin); printf("\n---------\n**This is the last chance to back out.\n\tContinue with the forgery Process (yes/no)? [no]:"); gets(inputString); if (strcmp(inputString,"yes")) { printf("Process was aborted.\n"); exit(0); } printf("-----\nContinuing...\n"); /* build data body chunk */ printf(" Building data body...\n"); sprintf(inputString,"%s %s\n%s %s\n%s %s\n%s %s\n%s %s\n",FROM, pseudoSender,NEWSGROUPS, newsgroups,SUBJECT,subjectLine, ORGANIZATION, organization, DISTRIBUTION, ((strcmp(distribution,NULL_STRING)) ? distribution : DIST_DEFAULT )); dataBody = (char*)malloc((strlen(inputString) + 1) * sizeof(char)); strcat(dataBody,inputString); if (strcmp(messageID, NULL_STRING)) { sprintf(inputString,"%s <%s>\n", MSGID, messageID); dataBody = (char*)realloc(dataBody,(strlen(dataBody) + strlen(inputString) + 1) * sizeof(char)); strcat(dataBody,inputString); } dataBody = (char*)realloc(dataBody,(strlen(dataBody) + strlen(body) + 1) * sizeof(char)); strcat(dataBody,body); printf(" Contacting nntp server...\n"); contact_relay(); /* speak that protocol slang */ printf(" Exchanging protocol slang...\n"); sprintf(buf,"%s\n", NNTP_INITIATE); writeln(buf); readln(outputString); /* monitor force feed of body into buf.... */ printf(" Passing the body of mail...\n"); writeln(dataBody); sprintf(buf,"\n%s\n", NNTP_EODATA); writeln(buf); readln(outputString); if (! strstr(outputString, GOOD_POST_ACK)) printf(" Server didn't send good post acknowledgment. Post probably failed.\n"); printf(" Closing connection...\n"); sprintf(buf,"%s\n", NNTP_CLOSE); writeln(buf); readln(outputString); if (strstr(outputString,GOOD_DISCONNECT)) printf("Received good acknowldegment\n"); else printf("\t ~~ Unrecognized command at socket closure.\n"); close(s); printf("------\nFinished... copy of sent message follows\n------\n%s\n------\n",dataBody); exit(0); } int contact_relay() { /* 0:host unreachable; 1:host connect but no posting allowed; 2: good host connect */ char serverSpew[BUFSIZ]; int i; if ((s=call_socket(nntpHost))==-1) return 0; do { readln(serverSpew); } while (! strstr(serverSpew,GOOD_CONNECT_STR)); if (strstr(serverSpew,BAD_NEWS)) return 1; else return 2; }